﻿/**
 *		网络通信模块
 *@date		2015年11月27日
 */
#ifndef OSS_SOCKET_H_
#define OSS_SOCKET_H_
#include <ossType.h>

//IP地址字符串的最大长度
#define OSS_IPV4_MAX			30

#ifndef OSS_INADDR_NONE
#define OSS_INADDR_NONE		0xffffffff
#endif

#define OSS_INADDR_BROADCAST	0xffffffff
#ifndef OSS_INVALID_SOCKET
#define OSS_INVALID_SOCKET  (Socket)(~0)
#endif

//socket错误定义
#define OSS_SOCKET_OK				0
#define OSS_SOCKET_INIT_ERR			-1
#define OSS_SOCKET_ERROR			-1


OSS_EXTERN_BEG
/**
 *		全局初始化socket
 *		在windows中调用WSAStartup，linux中为空函数
 *@return		成功返回 TRUE
 *				失败返回 FALSE
 *@author		吴建凰 2015年11月27日			
 */
Bool OssInitGlobalSocket();

/**
 *		全局逆初始化socket
 *@return		成功返回 TRUE
 *				失败返回 FALSE
 *@author		吴建凰 2015年11月27日	
 */
Bool OssDeinitGlobalSocket();

/**
 *		创建监听socket
 *@port			监听端口
 *@queueMax		等待队列的长度
 *@return		成功返回socket,
 *				失败返回OSS_INVALID_SOCKET
 *@author		吴建凰 2015年11月30日
 */
Socket OssCreateTcpServerSocket(Word port,DWord queueMax);

Socket OssCreateTcpServerSocketBindedIP(Word port,DWord queueMax,DWord dwBindedIp);

/**
 *		创建udp服务端socket
 *@port			监听端口
 *@return		成功返回socket,
 *				失败返回OSS_INVALID_SOCKET
 *@author		吴建凰 2015年11月30日
 */
Socket OssCreateUdpServerSocket(Word port);

/**
 *		创建UDPsocket
 *@return		返回创建好的udpsocket
 *				失败返回 OSS_INVALID_SOCKET
 *@author		吴建凰 2015年11月27日	
 */
Socket OssCreateUdpSocket();

/**
 *      创建广播socket
 *@return		返回创建好的广播socket
 *				失败返回 OSS_INVALID_SOCKET
 *@author		吴建凰 2015年11月27日	
 */
Socket OssCreateBroadcastSocket();

/**
 *		连接到服务器
 *@host			服务器的ip地址,可以是Ip字符串，也可以是域名
 *@port			服务器监听端口号
 *@return		成功返回socket,
 *				失败返回OSS_INVALID_SOCKET
 *@author		吴建凰 2015年11月30日
 */
Socket OssConnect(const char* host,Word port);

/**
 *		非阻塞连接 
 *@host			服务器的ip地址,可以是Ip字符串，也可以是域名
 *@port			服务器监听端口号
 *@timeout		连接超时时间
 *@return		成功返回socket,
 *				失败返回OSS_INVALID_SOCKET
 *@author		吴建凰 2015年11月30日
 */
Socket OssConnectWithTimeout(const char* host,Word port,DWord timeout);
Socket OssConnectWithTimeoutEx(DWord dwIp,Word dwPort,DWord dwTimeout);

/**
 *		绑定指定的端口，进行非阻塞连接 
 *@szHost			服务器的ip地址,可以是Ip字符串，也可以是域名
 *@wHostPort			服务器监听端口号
 *@dwTimeout		连接超时时间
 *@wBingPort      绑定的端口
 *@return		成功返回socket,
 *				失败返回OSS_INVALID_SOCKET
 *@author		吴建凰 2015年11月30日
 */
Socket OssConnectWithTimeoutAndPort(const char* szHost,Word wHostPort,DWord dwTimeout,Word wBingPort);

/**
 *		接收客户端连接
 *@sock_fd		监听socket
 *@lpIp			返回客户端IP地址，传入NULL则不需要返回
 *@lpPort		返回客户端端口号，传入NULL则不需要返回
 *@return		成功返回接收的socket
 *				失败返回OSS_INVALID_SOCKET
 *@author		吴建凰 2015年11月30日
 */
Socket OssAccept(Socket sock_fd,OUT DWord* lpIp,OUT Word *lpPort);

/**
 *		接收客户端连接
 *@sock_fd		监听socket
 *@lpIp			返回客户端IP地址，传入NULL则不需要返回
 *@lpPort		返回客户端端口号，传入NULL则不需要返回
 *@timeout		超时时间，单位毫秒
 *@return		成功返回接收的socket
 *				失败返回OSS_INVALID_SOCKET
 *@author		吴建凰 2015年11月30日
 */
Socket OssAcceptWithTimeout(Socket sock_fd,OUT DWord* lpIp,OUT Word *lpPort,DWord timeout);

/**
 *		释放socket
 *@sock_fd		需要释放的socket
 *@author		吴建凰 2015年11月27日	
 */
void OssCloseSocket(Socket sock_fd);

/**
 *		绑定端口
 *@s			需要绑定的socket
 *@port			绑定的端口号
 *@return		成功返回 TRUE
 *				失败返回 FALSE
 *@author		吴建凰 2015年11月27日	
 */
Bool OssBind(Socket s,Word port);
Bool OssBindIpAndPort(Socket s,DWord dwIp,Word port);

/**
 *		设置端口重用
 */
Bool OssSocketReuseAddr(Socket s);

/**
 *      设置异步模式
 *@bBlock       block状态，TRUE为阻塞模式，FALSE为非阻塞模式
 *@return       成功返回TRUE，是否返回FALSE
 */
Bool OssSetBlockSocket(Socket s,Bool bBlock);

/**
 *      设置socket发送的超时时间
 */
Bool OssSetSocketSendTimeout(Socket s,DWord dwTimeoutMs);

/**
 *      设置socket接收的超时时间
 */
Bool OssSetSocketRecvTimeout(Socket s,DWord dwTimeoutMs);

/**
 *      阻塞写
 *@sock_fd		socket句柄
 *@data			写入的数据
 *@len			需要写入数据的长度
 *@return		返回发送的字节数，如果失败则返回小于等于len的数
 *@author		吴建凰 2015年11月30日
 */
DWord OssSocketWrite(Socket sock_fd,const char* data,DWord len);

/**
 *      异步写
 *@notes        本方法的sock_fd必须是异步的socket,如果不是，请先调用OssSetBlockSocket设置 
 */
DWord OssSocketWriteWithTimeout(Socket sock_fd,char* data,DWord dwLen,DWord dwTimeout);

/**
 *      阻塞读
 *@sock_fd		SOCKET
 *@buffer		缓存
 *@nMax			缓存容量
 *@return		成功返回读到的数据大小
 *				断开连接返回 0 
 *				失败返回	-1
 *@author		吴建凰 2015年11月30日
 */
int OssSocketRead(Socket sock_fd,char* buffer,DWord nMax);

/**
 *      非阻塞读
 *@sock_fd		SOCKET
 *@buffer		缓存
 *@nMax			缓存容量
 *@timeout		超时时间，单位毫秒
 *@return		读取成功，返回读到的字节数
 *				超时，返回0
 *				socket错误，返回小于0的数
 *@author		吴建凰 2015年11月30日
 */
int OssSocketReadWithTimeout(Socket sock_fd,char* buffer,DWord nMax,DWord timeout);

/**
 *		将指定的udp发送数据
 *@sock_fd		SOCKET
 *@data			发送的数据
 *@len			发送数据的长度
 *@ip			目标IP
 *@port			目标端口
 *@return		实际发送的字节数
 *@author		吴建凰 2015年11月30日
 */
int OssSocketSendto(Socket sock_fd,char* data,DWord len,DWord ip,Word port);

/**
 *		接收udp发送过来的数据
 *@sock_fd		监听socket
 *@buffer		接收数据缓冲区
 *@nMax			缓冲区长度
 *@lpIp			返回客户端IP地址，传入NULL则不需要返回
 *@lpPort		返回客户端端口号，传入NULL则不需要返回
 *@return		成功返回实际接收到是数据长度
 *				失败返回 -1
 *@author		吴建凰 2015年11月30日
 */
int OssSocketRecvfrom(Socket sock_fd,char* buffer,DWord nMax,OUT DWord* lpIp,OUT Word *lpPort);

/**
 *		接收udp发送过来的数据
 *@sock_fd		监听socket
 *@buffer		接收数据缓冲区
 *@nMax			缓冲区长度
 *@lpIp			返回客户端IP地址，传入NULL则不需要返回
 *@lpPort		返回客户端端口号，传入NULL则不需要返回
 *@timeout		超时时间，单位毫秒
 *@return		成功返回实际接收到是数据长度
 *				超时返回 0
 *				失败返回 -1
 *@author		吴建凰 2015年11月30日
 */
int OssSocketRecvfromWithTimeout(Socket sock_fd,char* buffer,DWord nMax
						,DWord* lpIp,Word *lpPort,DWord timeout);


/**
 *      设置接收缓冲区大小
 */
Bool OssSetSocketRecvBufferSize(Socket s,DWord dwRecvBufMax);

/**
 *      设置发送缓冲区大小
 */
Bool OssSetSocketSendBufferSize(Socket s,DWord dwSendBufMax);

/**
 *      设置可以发送广播包
 */
Bool OssSetSocketBroadcastOption(Socket s,Bool bCanBroadcast);

/**
 *		获取本机的IP地址
 *@return		获取第一个取到的IP地址
 *@author		吴建凰 2015年11月30日
 */
DWord	OssGetOurIpAddress();
#define OssGetLocalIp  OssGetOurIpAddress

/**
 *		转换得到IP
 *@hostOrIp		域名或者是ip字符串
 *@return		成功返回4字节的IP地址
 *				失败返回OSS_INADDR_NONE
 *@author		吴建凰 2015年11月30日
 */
DWord	OssGetIp(const char* hostOrIp);

/**
 *		将IPV4转换为字符串
 *@ipaddr		IP地址
 *@return		成功返回转换后的IP字符串，需要及时保存
 *				失败返回NULL
 *@author		吴建凰 2015年11月30日
 */
char*	OssGetIpString(DWord ipaddr);

/**
 *      将网络字节序转换为本地字节序
 */
DWord OssNtohl(DWord dwLong);
DWord OssHtonl(DWord dwLong);
Word OssNtohs(Word wShort);
Word OssHtons(Word wShort);


OSS_EXTERN_END
#endif
